package chpt_04_03_clone_singleton;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.apache.commons.lang.SerializationUtils;
import org.springframework.aop.framework.adapter.AdvisorAdapter;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * @author Ping
 * @date 2023/3/23 8:44
 **/
public class CloneDemo {
    AdvisorAdapter dd ;
    Object object ;
    Cloneable cloneable ;
    public static void main(String args[]) throws Exception {
        Calendar calendar = Calendar.getInstance() ;
        calendar.set(2002, Calendar.FEBRUARY,12) ;
        Person stu1 = new Person("张三", 18, "FJNU",
                       "SE", calendar.getTime(), new Address("FUZHOU")) ;
        Person stu2 = stu1.clone() ;
        //Person deepStu2 = stu1.deepCopyBySerializable() ;
        Person deepStu2 = stu1.deepCopyByJSON() ;


        System.out.println("proptype: " + stu1) ;
        System.out.println("clone: " +stu2) ;
        System.out.println("deepClone: " +deepStu2) ;

        System.out.println(stu1 == deepStu2 ) ;
        System.out.println(stu1.equals(deepStu2) ) ;
        System.out.println(stu1.getClass() == deepStu2.getClass()) ;




    }


}
class Person implements Cloneable, Serializable {
    private String name ;
    private int age ;
    private String school ;
    private String major ;
    @JsonFormat
            (shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
    private Date brithday ;
    private Address address ;
    private Person friend ;

    @Override
    public Person clone() throws CloneNotSupportedException{
        Person p = (Person)super.clone() ;
        p.address = this.address.clone();
        return p ;
    }

    public Person deepCopyBySerializable() throws Exception {
     /*   byte[] data ;
        Person deepPerson ;
        // serializing
        try (ByteArrayOutputStream bop = new ByteArrayOutputStream() ;
             ObjectOutputStream oos = new ObjectOutputStream(bop) ;
        ) {
            oos.writeObject(this);
            data = bop.toByteArray() ;
        }
        // deserilizing
        try (ByteArrayInputStream bip = new ByteArrayInputStream(data);
             ObjectInputStream ois = new ObjectInputStream(bip);
        ) {
            deepPerson = (Person) ois.readObject() ;
        }*/
        return (Person)SerializationUtils.deserialize(
                SerializationUtils.serialize(this) );


    }
    public Person deepCopyByJSON() throws Exception {
        JsonMapper mapper = new JsonMapper( );
        return mapper.readValue(
                     mapper.writeValueAsString(this),
                     Person.class) ;
    }

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        this.brithday = new Date() ;
    }

    public Person(String name, int age, String school, String major, Date brithday) {
        this.name = name;
        this.age = age;
        this.school = school;
        this.major = major;
        this.brithday = brithday;
    }

    public Person(String name, int age, String school, String major, Date brithday, Address address) {
        this.name = name;
        this.age = age;
        this.school = school;
        this.major = major;
        this.brithday = brithday;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setBrithday(Date brithday) {
        this.brithday = brithday;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person)) return false;
        Person person = (Person) o;
        return name.equals(person.name) &&
                school.equals(person.school) &&
                major.equals(person.major);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, school, major);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", school='" + school + '\'' +
                ", major='" + major + '\'' +
                ", brithday=" + brithday +
                ", address=" + address +
                '}';
    }
}

class Address implements  Cloneable, Serializable {
    String address ;

    public Address(String address) {
        this.address = address;
    }
    @Override
    public Address clone() throws CloneNotSupportedException {
        Address address = (Address)super.clone() ;
        return address ;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}
